﻿#! /usr/bin/env python3
#coding=utf-8
"""
连接Mysql类数据库的通用类
作者: KydGroups
版本: 1.0.0
完成日期: 2024-06-02
修改记录:
"""

import pymysql

class KydPySql():
    """
    连接Mysql类数据库的通用类
    每次执行一次命令,都会连接一次数据库,不是一直保持连接
    """
    def __init__(self, user:str='', passwd:str='', dbname:str='',
                 host:str='127.0.0.1', port:int=3306, charset:str='utf8'):
        """
        :DESCRIPTION:
            连接初始化函数
        :PARAMS:
            user: 数据库用户名
            passwd: 用户密码
            dbname: 数据库名称
            host: Mysql服务器IP地址
            port: 连接端口
            charset: 字符编码格式
        :RETURNS:
            nothing
        """
        self.dbconfig = dict()
        self.dbconfig["user"] = user
        self.dbconfig["passwd"] = passwd
        self.dbconfig["db"] = dbname
        self.dbconfig["host"] = host
        self.dbconfig["port"] = port
        self.dbconfig["charset"] = charset


    def SetUserName(self, strUser:str=''):
        """
        :DESCRIPTION:
            设置数据库用户名
        :PARAMS:
            strUser: 用户名
        :RETURNS:
            True:设置成功 False:设置失败
        """
        if not strUser:
            return False
        else:
            self.dbconfig["user"] = strUser
            return True


    def SetPasswd(self, strPwd:str=''):
        """
        :DESCRIPTION:
            设置数据库密码
        :PARAMS:
            strPwd: 密码
        :RETURNS:
            True:设置成功 False:设置失败
        """
        if not strPwd:
            return False
        else:
            self.dbconfig["passwd"] = strPwd
            return True


    def SetDbName(self, strDb:str=''):
        """
        :DESCRIPTION:
            设置数据库名称
        :PARAMS:
            strDb: 数据库名称
        :RETURNS:
            True:设置成功 False:设置失败
        """
        if not strDb:
            return False
        else:
            self.dbconfig["db"] = strDb
            return True


    def SetHost(self, strHost:str='127.0.0.1'):
        """
        :DESCRIPTION:
            设置数据库主机IP地址
        :PARAMS:
            strHost: IP地址,默认使用本机地址
        :RETURNS:
            True:设置成功 False:设置失败
        """
        if not strHost:
            return False
        else:
            self.dbconfig["host"] = strHost
            return True


    def SetPort(self, nPort:int=3306):
        """
        :DESCRIPTION:
            设置数据库网络连接端口号
        :PARAMS:
            nPort: 端口号,默认3306f
        :RETURNS:
            True:设置成功 False:设置失败
        """
        if nPort <= 0:
            return False
        else:
            self.dbconfig["prot"] = nPort
            return True


    def SetCharset(self, strCharset:str='utf8'):
        """
        :DESCRIPTION:
            设置字符编码
        :PARAMS:
            strCharset: 字符编码,默认utf-8
        :RETURNS:
            True:设置成功 False:设置失败
        """
        if not strCharset:
            return False
        else:
            self.dbconfig["charset"] = strCharset
            return True


    def Ping(self):
        """
        :DESCRIPTION:
            测试数据库中否可以连接
        :PARAMS:
            nothing
        :RETURNS:
            True:可以连接 False:无法连接
        """
        try:
            db = pymysql.connect(**self.dbconfig)#连接数据库
            db.ping() #测试数据库是否存活
        except Exception:
            return False
        else:
            db.close()
            return True


    def Execute(self, strSql:str=''):
        """
        :DESCRIPTION:
            执行一条Sql指令
        :PARAMS:
            strSql: 字符串格式的指令,不需要;结尾
        :RETURNS:
            True:执行成功 False:执行失败
        """
        bSuccess = False #执行成功标志位
        db = None #连接的数据库
        cursor = None #数据库操作游标
        if not strSql: #如果没有传入参数
            return False
        if not isinstance(strSql, str): #如果传入的不是字符串参数
            return False
        try:
            db = pymysql.connect(**self.dbconfig) #连接数据库
            cursor = db.cursor() #使用cursor()方法获取操作游标
            cursor.execute(strSql) #执行指令
        except Exception: #出错时执行部分
            if not db:
                pass
            else:
                db.rollback() #如果发生错误则回滚
        else: #没有出错时执行部分
            db.commit() #提交到数据库执行
            bSuccess = True
        finally: #总是执行部分
            if not cursor:
                pass
            else:
                cursor.close() #关闭游标
            if not db:
                pass
            else:
                db.close() #关闭数据库
        return bSuccess


    def ExecuteMulti(self, listSql:list=[]):
        """
        :DESCRIPTION:
            批量执行多条指令
        :PARAMS:
            listSql: 指令列表
        :RETURNS:
            True:执行成功 False:执行失败
        """
        bSuccess = False #执行成功标志位
        db = None #连接的数据库
        cursor = None #数据库操作游标
        if not listSql:
            return False
        if not isinstance(listSql,list): #如果传入的参数不是list
            return False
        try:
            db = pymysql.connect(**self.dbconfig) #连接数据库
            cursor = db.cursor() #使用cursor()方法获取操作游标
            for strSql in listSql: #循环执行指令
                cursor.execute(strSql)#执行到数据库
        except Exception: #出错时执行的部分
            if not db:
                pass
            else:
                db.rollback()#如果发生错误则回滚
        else: #没有出错时执行的部分
            db.commit() #提交到数据库执行
            bSuccess = True
        finally: #总是执行部分
            if not cursor:
                pass
            else:
                cursor.close() #关闭游标
            if not db:
                pass
            else:
                db.close()#关闭数据库
        return bSuccess
        

    def Search(self, strSql:str='', isDict:bool=False):
        """
        :DESCRIPTION:
            执行查找指令,获取的结果以列表的形式返回
        :PARAMS:
            strSql: 查找指令
            isDict: 查找的结果是否以字典的形式返回
        :RETURNS:
            []:查找失败 List:查找到的数据,只有一条数据也以list类型返回
        """
        if not strSql: #如果没有传入查询指令
            return []
        db = None #数据库连接指针
        cursor = None #游标指针
        listSearch = [] #保存查询结果的列表
        listColumn = [] #保存查询结果中列名的列表
        try:
            db = pymysql.connect(**self.dbconfig) #连接数据库
            cursor = db.cursor() #使用cursor()方法获取操作游标
            cursor.execute(strSql) #执行查询操作
            column = cursor.description #查询结果的列名
            for col in column: #生成查询结果的列名列表
                listColumn.append(col[0])
            results = cursor.fetchall() #获取所有记录列表
            listSearch = list(results) #生成结果列表
            if len(listSearch) <= 0: #如果没有查询到数据
                listSearch = None
            else:
                if isDict: #如果要生成字典形式
                    dictList = list() #以字典形式保存的数据列表
                    cirLen = len(listColumn) #列名列表的长度
                    for item in listSearch: #循环处理每一个查询结果
                        singleDict = dict()
                        for num in range(cirLen):#循环处理每一行数据中的每一个列
                            singleDict[ listColumn[num] ] = item[ num ] #每个值与键对应
                        dictList.append( singleDict ) #将字典添加进列表
                    listSearch = dictList #结果置换
            cursor.close() #关闭游标
            db.close() #关闭数据库
            return listSearch
        except Exception: #出错执行的部分
            print("MySql------>>Search  错误指令没有查询到数据!")
            print(strSql)
            if not cursor:
                pass
            else:
                cursor.close() #关闭游标
            if not db:
                pass
            else:
                db.close() #关闭数据库连接
            return []
